package com.njtoyo.taxi.admin.service.data.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.njtoyo.taxi.admin.handler.common.DateIntervalHandler;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.Enum;
import com.njtoyo.taxi.admin.logic.cache.CacheRecommendCountLogic;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.RecommendChartPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.RecommendTotalPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.chart.ChartQueryWrapper;
import com.njtoyo.taxi.admin.service.data.RecommendService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@DS(Const.SECONDARY_DS)
public class RecommendServiceImpl implements RecommendService {

    @Autowired
    private CacheRecommendCountLogic cacheRecommendCountLogic;

    @Override
    public RestResult<List<RecommendChartPresenter>> chart(AdminUser adminUser, ChartQueryWrapper wrapper) {
        // 开始、结束时间
        Date current;
        Date startTime = null;
        Date endTime = null;
        int cycle = wrapper.getInterval().intValue() * -1;
        Enum.DateGroupType dateGroupType = wrapper.getDateGroupType();

        // 判断timeType
        switch (dateGroupType) {
            case customize:
                // 自定义
                if (Objects.isNull(wrapper.getStartTime()) || Objects.isNull(wrapper.getEndTime())) {
                    return RestResult.failed("开始时间或结束时间不能为空");
                }

                if (wrapper.getEndTime().before(wrapper.getStartTime())) {
                    return RestResult.failed("开始时间不能晚于结束时间");
                }

                int intervalMonth = DateIntervalHandler.intervalMonth(wrapper.getStartTime(), wrapper.getEndTime());

                // 间隔小于4个月
                if (intervalMonth < 4) {
                    // 和‘本月’逻辑相同
                    startTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(wrapper.getEndTime(), cycle));
                } else {
                    // 指定超过3个月份时，开始时间为指定开始时间的前一个月的月初；结束时间为结束时间的月末；
                    startTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(wrapper.getStartTime(), -1));
                }
                endTime = DateUtil.endOfMonth(wrapper.getEndTime());

                break;
            case day:
                // 今日
                current = DateUtil.beginOfDay(DateUtil.date());

                startTime = DateUtil.offsetDay(current, cycle);
                endTime = DateUtil.endOfDay(DateUtil.offsetDay(current, -1));

                break;
            case week:
                // 本周
                current = DateUtil.beginOfWeek(DateUtil.date());

                startTime = DateUtil.offsetWeek(current, cycle);
                endTime = DateUtil.endOfWeek(DateUtil.offsetWeek(current, -1));

                break;
            case month:
                // 本月
                wrapper.setStartTime(null);
                current = DateUtil.beginOfMonth(DateUtil.date());

                startTime = DateUtil.offsetMonth(current, cycle);
                endTime = DateUtil.endOfMonth(DateUtil.offsetMonth(current, -1));

                break;
        }

        List<RecommendChartPresenter> timeList;

        // 自定义
        if (dateGroupType.equals(Enum.DateGroupType.customize)) {
            timeList = getCyclesByCustomize(startTime, endTime);
        } else {
            // 今日、本周、本月
            timeList = getLastCyclesByType(dateGroupType, cycle);
        }

        List<RecommendTotalPresenter> charList = cacheRecommendCountLogic.getRecommendCountByCanton(dateGroupType, startTime, endTime, wrapper.getCantonId());

        for (RecommendChartPresenter timeItem : timeList) {
            for (RecommendTotalPresenter charItem : charList) {
                if (timeItem.getStartTimeStamp().equals(charItem.getStartTimeStamp())) {
                    timeItem.setTotal(charItem.getTotal());
                    break;
                }
            }
        }

        return RestResult.success(timeList);
    }

    /**
     * 根据时间类型获取最近N个周期
     */
    private List<RecommendChartPresenter> getLastCyclesByType(Enum.DateGroupType type, Integer cycle) {
        List<RecommendChartPresenter> res = new ArrayList<>();
        Date current = DateUtil.date();

        switch (type) {
            case day:
                // 日
                for (int i = cycle; i < 0; i++) {
                    RecommendChartPresenter item = new RecommendChartPresenter();
                    Date day = DateUtil.offsetDay(current, i);

                    item.setStartTimeStamp(DateUtil.beginOfDay(day));
                    item.setEndTimeStamp(DateUtil.endOfDay(day));

                    res.add(item);
                }
                break;
            case week:
                // 周
                for (int i = cycle; i < 0; i++) {
                    RecommendChartPresenter item = new RecommendChartPresenter();
                    Date week = DateUtil.offsetWeek(current, i);

                    item.setStartTimeStamp(DateUtil.beginOfWeek(week));
                    item.setEndTimeStamp(DateUtil.endOfWeek(week));

                    res.add(item);
                }
                break;
            case month:
                // 月
                for (int i = cycle; i < 0; i++) {
                    RecommendChartPresenter item = new RecommendChartPresenter();
                    Date month = DateUtil.offsetMonth(current, i);

                    item.setStartTimeStamp(DateUtil.beginOfMonth(month));
                    item.setEndTimeStamp(DateUtil.endOfMonth(month));

                    res.add(item);
                }
                break;
        }

        return res;
    }

    private List<RecommendChartPresenter> getCyclesByCustomize(Date startTime, Date endTime) {
        List<RecommendChartPresenter> res = new ArrayList<>();

        for (Date st = startTime; st.before(endTime); st = DateUtil.offsetMonth(st, 1)) {
            RecommendChartPresenter item = new RecommendChartPresenter();
            item.setStartTimeStamp(DateUtil.beginOfMonth(st));
            item.setEndTimeStamp(DateUtil.endOfMonth(st));

            res.add(item);
        }

        return res;
    }
}
